#include <stdio.h>
#include <stdlib.h>

void show(int n, int m, int x[n][m]);
void assign(int n, int m, int a[n][m], int b[n][m]);

int main(int argc, char const *argv[])
{
    // int n; // 随机值    
    // int a[n];
    // scanf("%d", &n); // 5/6


    // int b[ ][5] = {....}; // 三行五列

    // int  (b[3])  [5]; // b是一个具有3个元素的数组，每个元素都是 int [5]


    // int a[5]; // a: int *
    // int *p = a;

    // int b[3][5]; // b: int (*)[5] // 指向 int [5] 的指针
    // int (*k)[5] =  b;
    // int (*k2)[3][5] = &b;
    // k2++; // 向高地址移动60个字节

    // 重要结论：
    // 数组在代码中，会被系统自动转化为一个指向其首元素的指针
    // 例外：当出现sizeof、&的时候，数组不会被转换
    // printf("%d\n", sizeof(b)); // 60

    // a[i] ==>  *(a+i);

    // char s[] = "abcde";
    // printf("%c\n", s[1]);
    // printf("%c\n", *(s+1));
    // printf("%c\n", *(1+s));
    // printf("%c\n", 1[s]);

    // printf("%c\n", "wxyz"[1]);   //  |w|x|y|z|\0|
    // printf("%c\n", *("wxyz"+1)); //  |w|x|y|z|\0|
    // printf("%c\n", *(1+"wxyz")); //  |w|x|y|z|\0|
    // printf("%c\n", 1["wxyz"]);   //  |w|x|y|z|\0|

    // printf("%ld\n", sizeof("abcd")); // 此处 "abcd" 代表整个数组
    // printf("%p\n", &"abcd");        // 此处 "abcd" 代表整个数组
    // printf("%p\n",  "abcd");        // 此处 "abcd" 代表整个数组
    // printf("%p\n", &"abcd"+1);        // 此处 "abcd" 代表整个数组
    // printf("%p\n",  "abcd"+1);        // 此处 "abcd" 代表整个数组


    // struct node
    // {
    //     /* 结构体的其他成员 */
    //     // 成员1
    //     // 成员2
    //     // ... ...
        
    //     int  len;
    //     char data[0]; // 没有分配内存，而是提供一个入口
    // };

    // // 给结构体额外分配 10 个字节的内存。
    // struct node *p = malloc(sizeof(struct node) + 30);
    // //                           固定大小        可变大小
    // p->len = 10;

    // // 额外分配的内存可以通过 data 来使用
    // p->data[0] ~ p->data[29]


    // int n = 5; // n是一个局部变量，即在程序运行到此行时才在栈内存分配n
    // int a[n]; // 变长数组
    // a[0] = 1;
    // int b[5] = {1,2,3,4,5};
    // memcpy(a, b, 20);

    // f(n, a);

    int n, m;
    scanf("%d%d", &n, &m);
    int a[n][m];

    for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
            a[i][j] = rand()%1000; 
    }
    printf("a:\n");
    show(n, m, a);
   
    int b[n][m];
    assign(n, m, a, b); // 不可能完成的任务

    printf("b:\n");
    show(n, m, b); // 此处b被自动转化为 &b[0]，即一个int [m]的地址

    return 0;
}

// 二维数组的显示
void show(int n, int m, int x[n][m])
void show(int n, int m, int x[ ][m])
void show(int n, int m, int (*x)[m])
{
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
            printf("%d\t", x[i][j]);
        printf("\n");
    }
}

// 二维数组的拷贝
void assign(int n, int m, int a[n][m], int b[n][m])
{
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
            b[i][j] = a[i][j];
    }
}
